package service

import (
	"context"
	"github.com/kuangshp/go-utils/k"
	"github.com/shopspring/decimal"
	"insighttracking/query/bo"
	"insighttracking/query/dao"
	"insighttracking/query/model"
)

type _ordersDetailService struct{}

func (s _ordersDetailService) ModifyStatusByIdListApi(ctx context.Context, tx *dao.QueryTx, list []int64, status int64) error {
	if _, err := tx.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.ID.In(list...)).UpdateSimple(
		dao.OrdersDetailEntity.Status.Value(status),
	); err != nil {
		return err
	}
	return nil
}

func (s _ordersDetailService) ModifyStatusByOrderIdListApi(ctx context.Context, tx *dao.QueryTx, orderId int64, status int64) error {
	if _, err := tx.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.OrdersID.Eq(orderId)).UpdateSimple(
		dao.OrdersDetailEntity.Status.Value(status),
	); err != nil {
		return err
	}
	return nil
}

func (s _ordersDetailService) GetByIdListApi(ctx context.Context, list []int64) ([]*bo.OrderDetailBo, error) {
	//return dao.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.ID.In(list...)).Find()
	var detailEntities = make([]*bo.OrderDetailBo, 0)
	err := dao.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.ID.In(list...)).Select(
		dao.OrdersDetailEntity.ALL,
		dao.OrdersEntity.EnterpriseID,                 // 关联到enterprise表主键id
		dao.OrdersEntity.CustomerID,                   // 客户id,关联到enterprise_customer表主键id
		dao.OrdersEntity.SendGoodsDate,                // 发货日期
		dao.OrdersEntity.PurchaserID,                  // 采购员,关联到
		dao.OrdersEntity.TotalAmount,                  // 订单金额
		dao.OrdersEntity.TotalCount,                   // 订单商品数量
		dao.OrdersEntity.OrderNo,                      // 订单商品数量
		dao.SupplierEntity.ID.As("DefaultSupplierID"), // 默认供应商
		dao.EnterpriseCustomerEntity.Name.As("EnterpriseCustomerName"),
	).
		LeftJoin(dao.OrdersEntity, dao.OrdersEntity.ID.EqCol(dao.OrdersDetailEntity.OrdersID)).
		LeftJoin(dao.SpuEntity, dao.OrdersDetailEntity.SpuID.EqCol(dao.SpuEntity.ID)).
		LeftJoin(dao.SupplierEntity, dao.SupplierEntity.ID.EqCol(dao.SpuEntity.SupplierID)).
		LeftJoin(dao.EnterpriseCustomerEntity, dao.OrdersEntity.CustomerID.EqCol(dao.EnterpriseCustomerEntity.ID)).
		Scan(&detailEntities)
	return detailEntities, err
}

func (s _ordersDetailService) GetByOrderIdListApi(ctx context.Context, list []int64) ([]*model.OrdersDetailEntity, error) {
	return dao.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.OrdersID.In(list...)).Find()
}

func (s _ordersDetailService) GetListApi(ctx context.Context, ids []int64) ([]*model.OrdersDetailEntity, error) {
	return dao.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.ID.In(ids...)).Find()
}

func (s _ordersDetailService) GetWaitProduceListApi(ctx context.Context, list []int64) ([]*model.OrdersDetailEntity, error) {
	return dao.OrdersDetailEntity.WithContext(ctx).Where(
		dao.OrdersDetailEntity.ID.In(list...),
		dao.OrdersDetailEntity.IsProduction.Eq(0),
	).Find()
}

func (s _ordersDetailService) UpdateProduceStatusApi(ctx context.Context, tx *dao.QueryTx, list []int64, status int64) (err error) {
	_, err = tx.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.OrdersID.In(list...)).UpdateColumn(dao.OrdersDetailEntity.IsProduction, status)
	return
}

func (s _ordersDetailService) CreateBatchApi(ctx context.Context, tx *dao.QueryTx, data []*model.OrdersDetailEntity) error {
	if err := tx.OrdersDetailEntity.WithContext(ctx).CreateInBatches(data, len(data)); err != nil {
		return err
	}
	return nil
}

func (s _ordersDetailService) GetOrderDetailBySpuIdApi(ctx context.Context, spuId int64, orderIdList []int64) ([]*model.OrdersDetailEntity, error) {
	return dao.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.SpuID.Eq(spuId)).Where(dao.OrdersDetailEntity.OrdersID.In(orderIdList...)).Find()
}

func (s _ordersDetailService) GetByIdApi(ctx context.Context, id int64) (*model.OrdersDetailEntity, error) {
	return dao.OrdersDetailEntity.WithContext(ctx).Where(dao.OrdersDetailEntity.ID.Eq(id)).First()
}

func (s _ordersDetailService) GetTotalSpuApi(ctx context.Context, ids []int64) (totalMap map[int64]*bo.TotalOrderSpu, err error) {
	orderDetailEntities, err := s.GetByOrderIdListApi(ctx, ids)
	totalMap = make(map[int64]*bo.TotalOrderSpu)
	for _, orderDetailEntity := range orderDetailEntities {
		if orderDetailEntity.SpuID != 0 {
			if _, ok := totalMap[orderDetailEntity.SpuID]; !ok {
				totalMap[orderDetailEntity.SpuID] = &bo.TotalOrderSpu{
					SpuID:          orderDetailEntity.SpuID,
					SpuName:        orderDetailEntity.SnapshotName,
					Count:          orderDetailEntity.SpuCount,
					UnitName:       orderDetailEntity.SnapshotUnit,
					OrderIDs:       []int64{orderDetailEntity.OrdersID},
					OrderDetailIDs: []int64{orderDetailEntity.ID},
				}
			} else {
				totalMap[orderDetailEntity.SpuID].Count = totalMap[orderDetailEntity.SpuID].Count.Add(orderDetailEntity.SpuCount)
				orderIDs := totalMap[orderDetailEntity.SpuID].OrderIDs
				if !k.IsContains(orderIDs, orderDetailEntity.OrdersID) {
					orderIDs = append(orderIDs, orderDetailEntity.OrdersID)
					totalMap[orderDetailEntity.SpuID].OrderIDs = orderIDs
				}
				orderDetailIDs := totalMap[orderDetailEntity.SpuID].OrderDetailIDs
				if !k.IsContains(orderDetailIDs, orderDetailEntity.ID) {
					orderDetailIDs = append(orderDetailIDs, orderDetailEntity.ID)
					totalMap[orderDetailEntity.SpuID].OrderDetailIDs = orderDetailIDs
				}
			}
		} else {
			dishID := orderDetailEntity.DishesID
			dishRatio, err := DishService.GetSpuRatioApi(ctx, dishID)
			if err != nil {
				return nil, err
			}

			for _, item := range dishRatio {
				if _, ok := totalMap[item.SpuID]; !ok {
					totalMap[item.SpuID] = &bo.TotalOrderSpu{
						SpuID:          item.SpuID,
						SpuName:        item.Name,
						Count:          orderDetailEntity.SpuCount.Mul(decimal.New(item.Percent, 0)).Div(decimal.New(10000, 0)),
						UnitName:       item.UnitName,
						OrderIDs:       []int64{orderDetailEntity.OrdersID},
						OrderDetailIDs: []int64{orderDetailEntity.ID},
					}
				} else {
					totalMap[item.SpuID].Count = totalMap[item.SpuID].Count.Add(orderDetailEntity.SpuCount.Mul(decimal.New(item.Percent, 2)).Div(decimal.New(10000, 2)))
					orderIDs := totalMap[item.SpuID].OrderIDs
					if !k.IsContains(orderIDs, orderDetailEntity.OrdersID) {
						orderIDs = append(orderIDs, orderDetailEntity.OrdersID)
						totalMap[item.SpuID].OrderIDs = orderIDs
					}
					orderDetailIDs := totalMap[item.SpuID].OrderDetailIDs
					if !k.IsContains(orderDetailIDs, orderDetailEntity.ID) {
						orderDetailIDs = append(orderDetailIDs, orderDetailEntity.ID)
						totalMap[item.SpuID].OrderDetailIDs = orderDetailIDs
					}
				}
			}
		}
	}
	return
}

func (s _ordersDetailService) GetSpuBomByDetailsApi(ctx context.Context, orderDetailEntities []*bo.OrderDetailBo) (totalMap map[int64]*bo.TotalOrderSpuBom, err error) {
	totalMap = make(map[int64]*bo.TotalOrderSpuBom)
	for _, orderDetailEntity := range orderDetailEntities {
		if orderDetailEntity.SpuID != 0 {
			if _, ok := totalMap[orderDetailEntity.SpuID]; !ok {
				totalMap[orderDetailEntity.SpuID] = &bo.TotalOrderSpuBom{
					SpuID:                orderDetailEntity.SpuID,
					Count:                orderDetailEntity.SpuCount,
					OrderDetailID:        orderDetailEntity.ID,
					ExpectationGoodsDate: orderDetailEntity.SendGoodsDate,
				}
			} else {
				totalMap[orderDetailEntity.SpuID].Count = totalMap[orderDetailEntity.SpuID].Count.Add(orderDetailEntity.SpuCount)
			}
		} else {
			dishID := orderDetailEntity.DishesID
			dishRatio, err := DishService.GetSpuRatioApi(ctx, dishID)
			if err != nil {
				return nil, err
			}

			for _, item := range dishRatio {
				if _, ok := totalMap[item.SpuID]; !ok {
					totalMap[item.SpuID] = &bo.TotalOrderSpuBom{
						SpuID:                item.SpuID,
						Count:                orderDetailEntity.SpuCount.Mul(decimal.New(item.Percent, 0)).Div(decimal.New(10000, 0)),
						OrderDetailID:        orderDetailEntity.ID,
						ExpectationGoodsDate: orderDetailEntity.SendGoodsDate,
					}
				} else {
					totalMap[item.SpuID].Count = totalMap[item.SpuID].Count.Add(orderDetailEntity.SpuCount.Mul(decimal.New(item.Percent, 0)).Div(decimal.New(10000, 0)))
				}
			}
		}
	}
	return
}

var OrdersDetailService = new(_ordersDetailService)
